home *** CD-ROM | disk | FTP | other *** search
- /*
- File: 4D.c
- Author: K.R. Sloan, Jr.
- Last Modified: 11 September 1985
- 22 May 1986 by Tony DeRose
- 17 September 1986 by Jamie Painter
- 04 November 1986 by Karen Foltz
- Purpose: 4D homogeneous coordinate manipulation package
- */
-
- #include <stdio.h>
-
- #include "Math.h"
- #include "4D.h"
-
- #include "fast.c"
-
- typedef short bool;
- extern bool Kdebug;
-
-
- /* Exports */
- PointType4D Origin = {0.0,0.0,0.0,1.0};
- double epsilon = 0.00000000001;
-
- PointType4D CreatePoint4D(x,y,z,w)
- double x,y,z,w;
- {
- PointType4D NewPoint;
- NewPoint.P[0] = x;
- NewPoint.P[1] = y;
- NewPoint.P[2] = z;
- NewPoint.P[3] = w;
- return NewPoint;
- }
-
- /*
- ** Return the point 1 t-th along the way
- ** from P0 to P1.
- */
- extern PointType4D Ratio4D(P0,P1,t)
- PointType4D P0,P1;
- double t;
- {
- PointType4D P;
-
- P.P[X] = P0.P[X] + t * (P1.P[X] - P0.P[X]);
- P.P[Y] = P0.P[Y] + t * (P1.P[Y] - P0.P[Y]);
- P.P[Z] = P0.P[Z] + t * (P1.P[Z] - P0.P[Z]);
- P.P[W] = 1.0;
-
- return P;
- }
-
-
- extern PointType4D PxT4D(P,T)
- PointType4D P;
- TransformType4D T;
- {
- PointType4D Q;
-
- PxT4Dm(Q,P,T);
-
- return Q;
- }
-
-
- extern TransformType4D Transpose4D(T)
- TransformType4D T;
- {
- TransformType4D Tt;
- int i,j;
-
- for (i=0; i<4; i++) {
- for (j=0; j<4; j++) {
- Tt.T[i][j] = T.T[j][i];
- }
- }
- return Tt;
- }
-
-
-
-
- extern TransformType4D TxT4D(A, B)
- TransformType4D A, B;
- {
- TransformType4D C;
-
- TxT4Dm(C,A,B);
- return C;
- }
-
- extern TransformType4D Identity4D()
- {
- static TransformType4D I = { 1., 0., 0., 0.,
- 0., 1., 0., 0.,
- 0., 0., 1., 0.,
- 0., 0., 0., 1.};
- return I;
- }
-
- extern TransformType4D Translate4D(V)
- VectorType4D V;
- {
- TransformType4D T;
-
- T = Identity4D();
- T.T[0][3] = V.V[0];
- T.T[1][3] = V.V[1];
- T.T[2][3] = V.V[2];
- return T;
- }
-
- TransformType4D UniformScale4D(s)
- double s;
- {
- return Scale4D(CreatePoint4D(s,s,s,1.0));
- }
-
- extern TransformType4D Scale4D(P)
- PointType4D P;
- {
- TransformType4D T;
-
- T = Identity4D();
- T.T[0][0] = P.P[0];
- T.T[1][1] = P.P[1];
- T.T[2][2] = P.P[2];
- T.T[3][3] = P.P[3];
- return T;
- }
-
- extern TransformType4D Rotate4D(P0, P1, Radians)
- PointType4D P0, P1;
- double Radians;
- {
- TransformType4D T, R1, R2, R3, Rotate, Tmp;
- double w, a, b, c, l, v;
-
- w = P1.P[3]; a = P1.P[0]/w; b = P1.P[1]/w; c = P1.P[2]/w;
- w = P0.P[3]; a -= P0.P[0]/w; b -= P0.P[1]/w; c -= P0.P[2]/w;
-
- l = sqrt(a*a + b*b + c*c);
- if (l < epsilon)
- {
- fprintf(stderr,"Rotate4D: |P1-P0| is too small - can't rotate\n");
- Tmp = Identity4D();
- return Tmp;
- }
- else
- {
- a = a/l; b = b/l; c = c/l;
- }
-
- v = sqrt(b*b + c*c);
-
- P0.P[3] = -P0.P[3]; /* reverse direction by reversing w */
- T = Translate4D(Pdiff(P0,Origin));
-
- R1 = Identity4D(); R2 = R1; R3 = R1;
-
- if (v > epsilon)
- {
- R1.T[1][1] = c/v; R1.T[2][1] = b/v;
- R1.T[1][2] = -R1.T[2][1]; R1.T[2][2] = R1.T[1][1];
-
- }
-
- if ((v > epsilon) || (a > epsilon) || (a < (-epsilon)))
- {
- R2.T[0][0] = v; R2.T[2][0] = a;
- R2.T[0][2] = -R2.T[2][0]; R2.T[2][2] = v;
- }
-
- R3.T[0][0] = cos(Radians); R3.T[1][0] = -sin(Radians);
- R3.T[0][1] = -R3.T[1][0]; R3.T[1][1] = R3.T[0][0];
-
- TxT4Dm(Rotate,T,R1);
- TxT4Dm(Tmp,Rotate,R2);
- TxT4Dm(Rotate,Tmp,R3);
-
- R2.T[2][0] = -R2.T[2][0];
- R2.T[0][2] = -R2.T[0][2];
-
- R1.T[2][1] = -R1.T[2][1];
- R1.T[1][2] = -R1.T[1][2];
-
- T.T[0][3] = -T.T[0][3]; T.T[1][3] = -T.T[1][3]; T.T[2][3] = -T.T[2][3];
-
- TxT4Dm(Tmp,Rotate,R2);
- TxT4Dm(Rotate,Tmp,R1);
- TxT4Dm(Tmp,Rotate,T);
- return Tmp;
- }
-
- extern TransformType4D Perspective4D(f)
- double f;
- {
- TransformType4D P;
-
- P = Identity4D();
- if ((f < epsilon) && (f > (-epsilon)))
- {
- fprintf(stderr,"Perspective4D: f (%f) is too small.\n",f);
- if (f < 0.0) f = (-epsilon);
- else f = epsilon;
- }
- P.T[2][2] = 1.0/f; P.T[3][2] = 1.0/f;
- P.T[2][3] = -1.0; P.T[3][3] = 0.0;
- return P;
- }
-
- void PrintTransform4D(f,T)
- FILE *f;
- TransformType4D T;
- {
- int i,j;
-
- for (i=0; i<4; i++) {
- fprintf(f,"[");
- for (j=0; j<4; j++) {
- fprintf(f, " %lg ", T.T[j][i]);
- }
- fprintf(f,"]\n");
- }
- }
-
- void PrintPoint4D(f,P)
- FILE *f;
- PointType4D P;
- {
- fprintf(f,"[ %lg %lg %lg %lg ]", P.P[0], P.P[1], P.P[2], P.P[3]);
- }
-
- /*
- ** Vectors are represented as 4-tuples with the last component
- ** being 0. This representation allows them to be correctly transformed
- ** by homogeneous matrices.
- */
- VectorType4D CreateVector4D(a,b,c)
- double a,b,c;
- {
- VectorType4D NewVector;
-
- NewVector.V[0] = a;
- NewVector.V[1] = b;
- NewVector.V[2] = c;
- NewVector.V[3] = 0.0;
- return NewVector;
- }
-
- void PrintVector4D(f,v)
- FILE *f;
- VectorType4D v;
- {
- fprintf(f,"<%lg,%lg,%lg>\n", v.V[0],v.V[1],v.V[2]);
- }
-
- extern VectorType4D VxT4D(V,T)
- VectorType4D V;
- TransformType4D T;
- {
- VectorType4D Q;
- int i,k;
- double Qi;
-
- for (i = 0; i < 4; i++)
- {
- Qi = 0.0;
- for (k = 0; k < 4; k++)
- Qi += V.V[k] * T.T[i][k];
- Q.V[i] = Qi;
- }
- return Q;
- }
-
- VectorType4D NormalxT4D(N,Tinv)
- VectorType4D N;
- TransformType4D Tinv;
- {
- VectorType4D Np;
- int i,k;
- double Npi;
-
- for (i = 0; i < 3; i++)
- {
- Npi = 0.0;
- for (k = 0; k < 3; k++)
- Npi += N.V[k] * Tinv.T[k][i];
- Np.V[i] = Npi;
- }
- Np.V[3] = 0.0;
- return Np;
- }
-
- VectorType4D Cross4D( v1, v2)
- VectorType4D v1, v2;
- {
- VectorType4D v;
-
- v.V[0] = v1.V[1] * v2.V[2] - v1.V[2] * v2.V[1];
- v.V[1] = -(v1.V[0] * v2.V[2] - v1.V[2] * v2.V[0]);
- v.V[2] = v1.V[0] * v2.V[1] - v1.V[1] * v2.V[0];
- v.V[3] = 0.0;
-
- return v;
- }
-
- double Dot4D(v1,v2)
- VectorType4D v1, v2;
- {
- return v1.V[0] * v2.V[0] + v1.V[1] * v2.V[1] + v1.V[2] * v2.V[2];
- }
-
- double Vmag( v)
- VectorType4D v;
- {
- return sqrt( v.V[0]*v.V[0] + v.V[1]*v.V[1] + v.V[2]*v.V[2]);
- }
-
- VectorType4D Normalize( v)
- VectorType4D v;
- {
- VectorType4D vout;
- double l = sqrt( v.V[0]*v.V[0] + v.V[1]*v.V[1] + v.V[2]*v.V[2]);
-
- if (l < epsilon) {
- fprintf(stderr, "Can't normalize a zero vector.\n");
- /*exit(-1);*/
- vout = v;
- } else {
- vout.V[0] = v.V[0]/l;
- vout.V[1] = v.V[1]/l;
- vout.V[2] = v.V[2]/l;
- vout.V[3] = 0.0;
- }
-
- return vout;
- }
-
- /*
- ** Set W to 1
- */
- #ifdef NOT_INLINE
- extern void NormalizePoint(P1)
- PointType4D *P1;
- {
- register double *p = P1->P;
- register double w = p[W];
-
- if (w != 1.0) {
- /* We are assuming that the order in P is: X, Y, Z, W */
- *p++ /= w; *p++ /= w; *p++ /= w;
- *p = 1.0;
- }
- }
- #endif
-
- /*
- ** Return the vector V=P1-P0.
- */
- extern VectorType4D Pdiff(P1,P0)
- PointType4D P1,P0;
- {
- VectorType4D V;
-
- NormalizePoint(&P0);
- NormalizePoint(&P1);
-
- V.V[0] = P1.P[0] - P0.P[0];
- V.V[1] = P1.P[1] - P0.P[1];
- V.V[2] = P1.P[2] - P0.P[2];
- V.V[3] = 0.0;
-
- return V;
- }
-
- /*
- ** Return the vector s*V.
- */
- VectorType4D Vscale(s,V)
- double s;
- VectorType4D V;
- {
- V.V[X] *= s; V.V[Y] *= s; V.V[Z] *= s; V.V[W] = 0.0;
-
- return V;
- }
-
- /*
- ** Return the vector V1+V1.
- */
- VectorType4D Vadd(V1, V2)
- VectorType4D V1, V2;
- {
- VectorType4D V;
-
- V.V[X] = V1.V[X] + V2.V[X];
- V.V[Y] = V1.V[Y] + V2.V[Y];
- V.V[Z] = V1.V[Z] + V2.V[Z];
- V.V[W] = 0.0;
-
- return V;
- }
-
- /*
- ** Return the point P+V.
- */
- PointType4D PVadd(P,V)
- PointType4D P;
- VectorType4D V;
- {
- PointType4D p;
-
- NormalizePoint(&P);
- p.P[X] = P.P[X] + V.V[X];
- p.P[Y] = P.P[Y] + V.V[Y];
- p.P[Z] = P.P[Z] + V.V[Z];
- p.P[W] = 1.0;
-
- return p;
- }
-
- /* Return the negative of vector V */
- VectorType4D Vneg(V)
- VectorType4D V;
- {
- V.V[X] = -V.V[X];
- V.V[Y] = -V.V[Y];
- V.V[Z] = -V.V[Z];
- /* since V is a vector, V.V[W] is always 0. */
- return V;
- }
-
- /* Returns the midpoint to P1 and P2 */
- PointType4D Midpoint(P1,P2)
- PointType4D P1,P2;
- {
- PointType4D M;
-
- NormalizePoint(&P1);
- NormalizePoint(&P2);
- M.P[X] = (P1.P[X] + P2.P[X]) / 2.;
- M.P[Y] = (P1.P[Y] + P2.P[Y]) / 2.;
- M.P[Z] = (P1.P[Z] + P2.P[Z]) / 2.;
- M.P[W] = 1.;
- return M;
- }
-
-